﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Asteroids
{
    public abstract class SpaceItem
    {
        protected AnimatedSprite m_sprite;
        protected float m_maxThrust, m_accelFactor, m_mass, m_pctDistMoved;
        protected Vector2 m_velocity, m_position;
        public int radius, health, gold;
        public float rotation;
        protected Random m_random;
        public Upgrade[] upgrades;
        protected int m_exp, m_model, m_moveChance, m_maxHealth;
        public Boolean touched, m_exploder;

        public float friction = 0.01f;
        public float rotationFactor = 0.05f;
        protected float m_maxSpeed = 5;

        public virtual Boolean exploder
        {
            get { return m_exploder; }
            set { m_exploder = value; }
        }
        public float pctDistMoved
        {
            get { return m_pctDistMoved; }
            set { m_pctDistMoved = value; }
        }

        public Vector2 ratioVelocity
        {
            set
            {
                float ratio1 = Math.Abs(value.X) / m_maxSpeed;
                float ratio2 = Math.Abs(value.Y) / m_maxSpeed;
                float trueratio = ratio1>ratio2 ? ratio1 : ratio2;
                m_velocity = value / trueratio; 
            }
        }

        public Vector2 velocity
        {
            get { return m_velocity; }
            set 
            { 
                m_velocity.X = MathHelper.Clamp(value.X, -1 * m_maxSpeed, m_maxSpeed);
                m_velocity.Y = MathHelper.Clamp(value.Y, -1 * m_maxSpeed, m_maxSpeed);
            }
        }

        public Vector2 thrust
        {
            get { return m_velocity; }
            set
            {
                if ((Math.Abs(m_velocity.X) > m_maxThrust))
                {
                    if ((value.X < m_velocity.X && m_velocity.X > 0) || (value.X > m_velocity.X && m_velocity.X < 0))
                        m_velocity.X = value.X;
                }
                else
                {
                    m_velocity.X = value.X;
                }

                if ((Math.Abs(m_velocity.Y) > m_maxThrust))
                {
                    if ((value.Y < m_velocity.Y && m_velocity.Y > 0) || (value.Y > m_velocity.Y && m_velocity.Y < 0))
                        m_velocity.Y = value.Y;
                }
                else
                {
                    m_velocity.Y = value.Y;
                }
            }
        }

        public Vector2 position
        {
            get { return m_position; }
            set { m_position = value; }
        }

        public Vector2 centerPosition
        {
            get { return new Vector2(m_position.X + radius, m_position.Y + radius); }
            set { m_position = new Vector2(value.X - radius, value.Y - radius); }
        }

        public float accelFactor
        {
            get {return m_accelFactor;}
            set { m_accelFactor = MathHelper.Clamp(value, 0, 1); }
        }

        public float maxSpeed
        {
            get { return m_maxSpeed; }
            set { m_maxSpeed = value; }
        }

        public float mass
        {
            get { return m_mass; }
            set { m_mass = MathHelper.Clamp(value, 0, value); }
        }

        public int maxHealth
        {
            get { return m_maxHealth; }
            set { m_maxHealth = value; }
        }

        public int expFactor
        {
            get { return m_exp; }
        }

        public AnimatedSprite sprite
        {
            get { return m_sprite; }
        }

        public SpaceItem(Vector2 pos, Vector2 vel)
        {
            m_random = new Random();
            upgrades = new Upgrade[Game1.NUM_UPGRADES];
            Game1.upgrades.CopyTo(upgrades,0);
            m_accelFactor = 0;
            m_exp = 0;
            gold = 0;
            rotation = 0;
            position = pos;
            velocity = vel;
            touched = false; 
        }

        public virtual void Draw(SpriteBatch sb)
        {
            m_sprite.Draw(sb, position, centerPosition, rotation % (float)(Math.PI * 2));
        }

        public virtual void Update(GameTime gametime)
        {
            m_sprite.Update(gametime);
            m_pctDistMoved = 0;
        }

        public virtual Explosion Die()
        {
            return new Explosion(0, centerPosition, m_velocity);
        }
    }

    public struct ItemModel
    {
        public Texture2D texture;
        public float maxSpeed, accelFactor, mass;
        public int radius, health, gold, exp, moveChance, damage;
        public int[] upgrades;
        public Boolean isBullet;
    }

    public struct Upgrade
    {
        public Texture2D texture;
        public int cost, maxLevel, maxAmmo;
        public int level, ammo, range;
        public TimeSpan cooldown, lastUsed, drawTime, cooldownDec;
        public String name, shortName;
    }

    public struct Notification
    {
        public String message;
        public TimeSpan creationTime;
    }
}
